package edu.cs.usask.ca.silver.persistence.datasource;

import javax.sql.DataSource;

import org.apache.derby.jdbc.ClientXADataSource;

import junit.framework.Assert;

import com.atomikos.jdbc.AtomikosDataSourceBean;

import edu.cs.usask.ca.silver.definitions.SystemProperties;

public class DataSourceFactory {


	/**
	 * Create a Derby datasource with the specified database name, user name and
	 * password. if database name is not given, then we will use SilverDb in
	 * user home directory. The datasource pool size is default to 1. The
	 * Connection timeout is default to 60 sec.
	 * 
	 * @param databaseLoc
	 *            - Location of the database containing the db name
	 * @param user
	 *            - login username (set to null to ignore using user)
	 * @param pass
	 *            - login password (set to null to ignore using password)
	 * @param poolSize
	 *            - size of connection pool
	 * @param connTimeOut
	 *            - connection timeout
	 * @return A configured Datasource with Connection to Derby embedded db.
	 */
	public static final DataSource createEmbeddedDerbyDataSource(
			String databaseLoc, String user, String pass,
			int poolSize, int connTimeOut) {

		// Find or construct a datasource instance;
		AtomikosDataSourceBean ds = new AtomikosDataSourceBean();

		org.apache.derby.jdbc.EmbeddedXADataSource derbyDs = new org.apache.derby.jdbc.EmbeddedXADataSource();

		derbyDs.setCreateDatabase("create");

		if (databaseLoc != null) {
			derbyDs.setDatabaseName(databaseLoc);
		} else {
			derbyDs.setDatabaseName(SystemProperties.USER_HOME
					+ SystemProperties.FILE_SEPARATOR + "SilverDb");
		}

		derbyDs.setUser(user);
		derbyDs.setPassword(pass);

		Assert.assertNotNull(derbyDs);
		ds.setXaDataSource(derbyDs);
		final String resourceName = "local/" + databaseLoc;
		ds.setUniqueResourceName(resourceName);

		// OPTIONAL: what is the pool size?
		if (poolSize < 0)
			ds.setPoolSize(80);
		else
			ds.setPoolSize(poolSize);

		// OPTIONAL: how long until the pool thread checks liveness of
		// connections?
		if (connTimeOut < 0)
			ds.setBorrowConnectionTimeout(60);
		else
			ds.setBorrowConnectionTimeout(connTimeOut);

		// NOTE: the resulting datasource can be bound in JNDI where
		// available

		Assert.assertNotNull(ds);
		return ds;
	}

	public static final DataSource createNetworkClientDerbyDataSource(
			String databaseName, String serverName,
			int portNumber, String user, String pass, int poolSize,
			int connTimeOut) {
		AtomikosDataSourceBean ds = new AtomikosDataSourceBean();

		org.apache.derby.jdbc.ClientXADataSource derbyDs = new ClientXADataSource();

		derbyDs.setCreateDatabase("create");

		
		derbyDs.setDatabaseName(databaseName);
		derbyDs.setUser(user);
		derbyDs.setPassword(pass);
		derbyDs.setServerName(serverName);
		derbyDs.setPortNumber(portNumber);
		derbyDs.setCreateDatabase("create");
		

		Assert.assertNotNull(derbyDs);
		ds.setXaDataSource(derbyDs);
		final String resourceName = "remote/" + serverName
				+ portNumber + databaseName;
		ds.setUniqueResourceName(resourceName);

		// OPTIONAL: what is the pool size?
		if (poolSize < 0)
			ds.setPoolSize(50);
		else
			ds.setPoolSize(poolSize);

		// OPTIONAL: how long until the pool thread checks liveness of
		// connections?
		if (connTimeOut < 0)
			ds.setBorrowConnectionTimeout(100);
		else
			ds.setBorrowConnectionTimeout(connTimeOut);

		// NOTE: the resulting datasource can be bound in JNDI where
		// available

		Assert.assertNotNull(ds);
		return ds;
	}

	/**
	 * Create a PgSQL datasource with the specified database name, user name and
	 * password. if database name is not given, then we will use SilverDb in
	 * user home directory. The datasource pool size is default to 1. The
	 * Connection timeout is default to 60 sec.
	 * 
	 * @param databaseLoc
	 *            - Location of the database containing the db name
	 * @param user
	 *            - login username (set to null to ignore using user)
	 * @param pass
	 *            - login password (set to null to ignore using password)
	 * @param poolSize
	 *            - size of connection pool
	 * @param connTimeOut
	 *            - connection timeout
	 * @return A configured Datasource with Connection to Derby embedded db.
	 */
	public static final DataSource createPgSQLDataSource(String serverLoc,
			String dataabaseName, int port, String user, String pass,
			int poolSize, int connTimeOut) {
		final String resourceName = serverLoc + port + dataabaseName
				+ "/xa/PgSQLDataSource";

		// Find or construct a datasource instance;
		AtomikosDataSourceBean ds = new AtomikosDataSourceBean();

		if (ds.getXaDataSource() != null) {
			if (ds.getUniqueResourceName().compareTo(resourceName) == 0)
				return ds;
		}

		org.postgresql.xa.PGXADataSource pgSqlDs = new org.postgresql.xa.PGXADataSource();

		pgSqlDs.setDatabaseName(dataabaseName);
		pgSqlDs.setUser(user);
		pgSqlDs.setPassword(pass);
		pgSqlDs.setServerName(serverLoc);
		pgSqlDs.setPortNumber(port);

		ds.setXaDataSource(pgSqlDs);

		if (ds.getUniqueResourceName() == null) {
			ds.setUniqueResourceName(resourceName);
		} else if (!ds.getUniqueResourceName().equalsIgnoreCase(resourceName)) {
			ds.setUniqueResourceName(resourceName);
		}

		// OPTIONAL: what is the pool size?
		if (poolSize < 0)
			ds.setPoolSize(0);
		else
			ds.setPoolSize(poolSize);

		// OPTIONAL: how long until the pool thread checks liveness of
		// connections?
		if (connTimeOut < 0)
			ds.setBorrowConnectionTimeout(60);
		else
			ds.setBorrowConnectionTimeout(connTimeOut);

		// NOTE: the resulting datasource can be bound in JNDI where
		// available
		return ds;
	}

}
